package com.chuangke.flow.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.chuangke.common.enums.OrderStatusEnum;
import com.chuangke.common.exception.ChuangkeException;
import com.chuangke.common.utils.SpringContextUtil;
import com.chuangke.flow.constant.FlowConstant;
import com.chuangke.flow.dao.FlowHiFlowDao;
import com.chuangke.flow.dao.FlowHiNodeDao;
import com.chuangke.flow.dao.FlowHiNodeProcessorDao;
import com.chuangke.flow.dao.FlowHiTaskLogDao;
import com.chuangke.flow.dao.FlowHiVariableDao;
import com.chuangke.flow.dao.FlowRuFlowDao;
import com.chuangke.flow.dao.FlowRuNodeDao;
import com.chuangke.flow.dao.FlowRuNodeProcessorDao;
import com.chuangke.flow.dao.FlowRuTaskDao;
import com.chuangke.flow.dao.FlowRuVariableDao;
import com.chuangke.flow.domain.FlowAuditResult;
import com.chuangke.flow.domain.FlowHandler;
import com.chuangke.flow.entity.FlowHiFlow;
import com.chuangke.flow.entity.FlowHiTaskLog;
import com.chuangke.flow.entity.FlowRuFlow;
import com.chuangke.flow.entity.FlowRuNode;
import com.chuangke.flow.entity.FlowRuTask;
import com.chuangke.flow.enums.FlowNodeStatusEnum;
import com.chuangke.flow.listener.Listener;
import com.chuangke.flow.listener.ListenerVariable;
import com.chuangke.flow.service.FlowInstanceService;
import com.chuangke.flow.service.FlowTaskService;
import com.chuangke.flow.util.FlowUtils;
import com.chuangke.framework.util.OrderFlowUtilsV2;

import cn.hutool.core.util.StrUtil;

@Service
public class FlowTaskServiceImpl implements FlowTaskService {

    @Autowired
    private FlowRuFlowDao flowRuFlowDao;
    @Autowired
    private FlowRuNodeDao flowRuNodeDao;
    @Autowired
    private FlowRuNodeProcessorDao flowRuNodeProcessorDao;
    @Autowired
    private FlowRuTaskDao flowRuTaskDao;
    @Autowired
    private FlowRuVariableDao flowRuVariableDao;

    @Autowired
    private FlowHiFlowDao flowHiFlowDao;
    @Autowired
    private FlowHiNodeDao flowHiNodeDao;
    @Autowired
    private FlowHiNodeProcessorDao flowHiNodeProcessorDao;
    @Autowired
    private FlowHiTaskLogDao flowHiTaskLogDao;
    @Autowired
    private FlowHiVariableDao flowHiVariableDao;

    @Autowired
    private FlowInstanceService flowInstanceService ;

    /**
     * 获取当前用户可以处理的任务
     *
     * @param handlerList
     * @param flowAuditResult
     * @return
     */
    private List<FlowRuTask> getCurrentUserTask(List<FlowHandler> handlerList, FlowAuditResult flowAuditResult) {
        // 根据需要审核的单据，获取所有可以审核的任务
        // 正常审核所有的userId为一个，但是已审核节点的自动跳过，userId可能不不同，所以需要拼接上每个任务的单据和对应的审核人
        QueryWrapper<FlowRuTask> query = new QueryWrapper<>();
        query.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode());
        query.lambda().and(wrapper -> handlerList.forEach(handle -> wrapper.or(wp -> {
            wp.eq(FlowRuTask::getOrderId, handle.getBusinessKey());
            // 这个标志只有单据提交的时候限制，正常审核都要加用户过滤
            if (handle.isSubmitRestrictTaskUser()) {
                wp.eq(FlowRuTask::getUserId, handle.getUserId());
            }
        })));
        List<FlowRuTask> currentTaskList = flowRuTaskDao.list(query);
        if (CollectionUtils.isEmpty(currentTaskList)) {
            throw new ChuangkeException("未找到待处理流程审批任务信息");
        }

        List<String> existsTaskOrderList = currentTaskList.stream().map(FlowRuTask::getOrderId)
                .collect(Collectors.toList());
        handlerList.forEach(handle -> {
            if (!existsTaskOrderList.contains(handle.getBusinessKey())) {
                flowAuditResult.failOrderId(handle.getBusinessKey())
                        .failMsg(String.format("单据[%s]未启动流程或已审批完成，无法审批", handle.getBusinessKey()));
            }
        });

        return currentTaskList;
    }

    /**
     * 批量审批只支持同一类单据
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public FlowAuditResult complete(List<FlowHandler> handlerList) {
        FlowAuditResult flowAuditResult = new FlowAuditResult();

        /**************** 审批校验 ***********************/
        // @校验1:校验审批数据集是否为空
        if (CollectionUtils.isEmpty(handlerList)) {
            return flowAuditResult;
        }

        // @校验2:校验审批状态是否正确
        // 批量审批肯定是同样的审批结果，这里取第一个审批结果
        String status = FlowConstant.OPT_STATE_MAP.get(handlerList.get(0).getAudit());
        if (StrUtil.isBlank(status)) {
            throw new ChuangkeException(String.format("审批标识：【%s】无效", status));
        }

        // @校验3:校验是否有可以审核的单据
        // 根据需要审核的单据，获取所有可以审核的任务
        List<FlowRuTask> currentTaskList = getCurrentUserTask(handlerList, flowAuditResult);
        if (CollectionUtils.isEmpty(currentTaskList)) {
            throw new ChuangkeException("未找到待处理流程审批任务信息");
        }

        /************************ 审批任务逻辑处理开始 ******************************/
        // 批量审批肯定是同样的审批意见，这里取第一个审批意见
        String auditMessage = handlerList.get(0).getMessage();
        List<String> currentTaskIdList = currentTaskList.stream().map(FlowRuTask::getId).collect(Collectors.toList());
        // @1: 更新处理日志的结束时间、审批状态、审批意见
        flowHiTaskLogDao.update(new UpdateWrapper<FlowHiTaskLog>().lambda().set(FlowHiTaskLog::getStatus, status)
                .set(FlowHiTaskLog::getComments, auditMessage).set(FlowHiTaskLog::getEndAt, new Date())
                .in(FlowHiTaskLog::getTaskId, currentTaskIdList)
                .eq(FlowHiTaskLog::getStatus, FlowNodeStatusEnum.unhandle.getCode()));

        if (FlowNodeStatusEnum.agree.getCode().equals(status)) {
            agreeBatch(currentTaskList, handlerList, status, auditMessage);

            // 2022-11-01添加支持流程审批人已审核，后续节点还有要审核的自动跳过
//            agreeJump(handlerList);
        } else {
            //对于退回的单据，可以把待处理的任务都删除掉
            executeRemoveUnHandleTask4Reject(currentTaskList);

            // 如果选择了退回节点，退回至指定节点；如果没有选择，退回到开始节点
            String rejectNodeId = handlerList.get(0).getRejectNodeId();
            if (StrUtil.isBlank(rejectNodeId)) {
                rejectBatch(currentTaskList);
            } else {
                rejectBatch(currentTaskList, handlerList, flowAuditResult);
            }
        }

        List<String> existsTaskOrderList = currentTaskList.stream().map(FlowRuTask::getOrderId)
                .distinct().collect(Collectors.toList());
        flowAuditResult.setSuccessCount(existsTaskOrderList.size());
        flowAuditResult.setSuccessOrderIdList(existsTaskOrderList);
        return flowAuditResult;
    }

    /**
     * 对于退回的单据，可以把待处理的任务都删除掉
     *
     * @param currentTaskList
     */
    private void executeRemoveUnHandleTask4Reject(List<FlowRuTask> currentTaskList) {
        QueryWrapper<FlowHiTaskLog> uw2 = new QueryWrapper<>();
        uw2.lambda().eq(FlowHiTaskLog::getStatus, FlowNodeStatusEnum.unhandle.getCode());
        uw2.lambda().and(wrapper -> currentTaskList.forEach(cTask -> wrapper.or(wp -> wp.eq(FlowHiTaskLog::getNodeId, cTask.getNodeId())
                .eq(FlowRuTask::getOrderId, cTask.getOrderId())
                .eq(FlowRuTask::getOrderNum, cTask.getOrderNum()))));

        flowHiTaskLogDao.remove(uw2);
    }

    /**
     * 审批的时候如果当前审批人之前已经审批同意，则当前节点自动审批通过
     *
     * @param handlerList
     */
//	@Async
    public void agreeJump(List<FlowHandler> handlerList) {
        List<String> orderList = handlerList.stream().map(FlowHandler::getBusinessKey).collect(Collectors.toList());
        QueryWrapper<FlowRuTask> query = new QueryWrapper<>();
        query.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.agree.getCode())
                .in(FlowRuTask::getOrderId, orderList)
                .exists("select 1 from flow_ru_task b where flow_ru_task.order_id=b.order_id and flow_ru_task.user_id=b.user_id and b.status={0} ",
                        FlowNodeStatusEnum.unhandle.getCode());
        List<FlowRuTask> taskList = flowRuTaskDao.list(query);
        if (CollectionUtils.isEmpty(taskList)) {
            return;
        }

        Map<String, FlowHandler> handleMap = handlerList.stream()
                .collect(Collectors.toMap(FlowHandler::getBusinessKey, Function.identity(), (key1, key2) -> key2));

        List<FlowHandler> jumpHandlerList = taskList.stream().map(task -> {
            FlowHandler handle = new FlowHandler();
            handle.setAudit(FlowNodeStatusEnum.agree.name());
            handle.setBusinessKey(task.getOrderId());
            handle.setUserId(task.getUserId());
            handle.setMessage("自动审批");
            handle.setVariables(handleMap.get(task.getOrderId()).getVariables());
            return handle;
        }).collect(Collectors.toList());

        ((FlowTaskService) AopContext.currentProxy()).complete(jumpHandlerList);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public FlowAuditResult revoke(List<FlowHandler> handlerList) {
        FlowAuditResult flowAuditResult = new FlowAuditResult();
        if (CollectionUtils.isEmpty(handlerList)) {
            return flowAuditResult;
        }

        // 批量审批肯定是同样的审批结果，这里取第一个审批结果
        String status = FlowConstant.OPT_STATE_MAP.get(handlerList.get(0).getAudit());
        if (StrUtil.isBlank(status)) {
            throw new ChuangkeException("未找到合理的审批标识");
        }

        // @1:获取到当前正在执行的任务
        List<FlowRuTask> taskListn = getCurrentHandleTaskByOrderIds(handlerList, flowAuditResult);
        if (CollectionUtils.isEmpty(taskListn)) {
            return flowAuditResult;
        }

        // 获取退回人
        String userId = handlerList.get(0).getUserId();

        // @2: 根据当前执行中的任务获取可以撤回的任务
        List<FlowRuTask> canRevokeTaskList = getCanRevokeTaskList(userId, taskListn, flowAuditResult);
        if (CollectionUtils.isEmpty(canRevokeTaskList)) {
            return flowAuditResult;
        }

		/*
		  执行审核，并将任务放到历史任务中
		 */
        // 处理任务状态，当前节点置成未启动，上一节点置成待处理
        handleRevokeRuTask(canRevokeTaskList);

        // 处理任务日志
        handleRevokeHiTaskLog(canRevokeTaskList, handlerList);

        // 获取撤回到第一个节点的任务
        canRevokeTaskList = canRevokeTaskList.stream().filter(task -> task.getOrderNum() == 1)
                .collect(Collectors.toList());
        handleSubmitRevoke(canRevokeTaskList);

        List<String> existsTaskOrderList = canRevokeTaskList.stream().map(FlowRuTask::getOrderId)
                .distinct().collect(Collectors.toList());
        flowAuditResult.setSuccessCount(existsTaskOrderList.size());
        flowAuditResult.setSuccessOrderIdList(existsTaskOrderList);

        return flowAuditResult;
    }

    /**
     * 处理提交的撤回
     *
     * @param canRevokeTaskList 撤回到第一个节点的任务
     */
    private void handleSubmitRevoke(List<FlowRuTask> canRevokeTaskList) {
        if (CollectionUtils.isEmpty(canRevokeTaskList)) {
            return;
        }
        FlowRuFlow ruFlow = flowRuFlowDao.getById(canRevokeTaskList.get(0).getFlowId());
        List<String> canRevokeFlowIdList = canRevokeTaskList.stream().map(FlowRuTask::getFlowId)
                .collect(Collectors.toList());

        List<String> canRevokeOrderIdList = canRevokeTaskList.stream().map(FlowRuTask::getOrderId)
                .collect(Collectors.toList());

        flowHiFlowDao.update(
                new UpdateWrapper<FlowHiFlow>().lambda().set(FlowHiFlow::getOrderStatus, OrderStatusEnum.EDIT.getCode())
                        .in(FlowHiFlow::getId, canRevokeFlowIdList));
//        FlowUtils.handleOrderBatch(ruFlow.getOrderService(), FlowConstant.HANDLE_ORDER_CANCEL_SUBMIT_BATCH,
//                canRevokeOrderIdList);
        if(ruFlow.getOrderService().contains(".")) {
        	FlowUtils.handleOrderBatch(ruFlow.getOrderService(), FlowConstant.HANDLE_ORDER_CANCEL_SUBMIT_BATCH, canRevokeOrderIdList);
        }else {
        	OrderFlowUtilsV2.cancelSubmitBatch(ruFlow.getOrderService(), canRevokeOrderIdList);
        }
    }

    private void agreeBatch(List<FlowRuTask> currentTaskList, List<FlowHandler> handlerList, String status,
                            String auditMessage) {
        List<String> currentTaskIdList = currentTaskList.stream().map(FlowRuTask::getId).collect(Collectors.toList());
        // @1: 更新当前待办任务的处理状态和处理意见;对于同意的处理，status肯定是同意
        flowRuTaskDao.update(new UpdateWrapper<FlowRuTask>().lambda().set(FlowRuTask::getStatus, status)
                .set(FlowRuTask::getComments, auditMessage).in(FlowRuTask::getId, currentTaskIdList));

        // 批量审批只支持同一类单据,取第一个任务的单据服务
        FlowRuFlow ruFlow = flowRuFlowDao.getById(currentTaskList.get(0).getFlowId());
        String orderService = ruFlow.getOrderService();

        // 对于第一个任务节点处理，即单据提交操作执行逻辑
        excuteSubmitFlow(orderService, currentTaskList, handlerList);

        /*
         如果是会签，查找同级并且是待处理的任务，如果有任务不需要处理，如果没有任务，开启下一个节点任务。
         如果是或签，将同级的待处理任务，更新成nohandle，并开启下一个节点。
         */
//		List<String> counterSignHuiqList = getHuiqOrderIdList(currentTaskList);
        Map<String, List<String>> counterSignMap = getHuiqOrderIdList(currentTaskList);
        List<String> counterSignHuiqList = counterSignMap.get("huiq");
        List<String> counterSignHuoqList = counterSignMap.get("huoq");

        /*对于或签的任务，如果是有一个人审核了，其他的任务状态设置成nohandle*/
        executeNoHandleTask(counterSignHuoqList, currentTaskList);

        List<String> canNotStartNextTaskOrderIdList = getCanNotStartNextTaskOrderIdList(counterSignHuiqList,
                currentTaskList);
        List<FlowRuTask> canStartNextTaskList = currentTaskList.stream()
                .filter(task -> !canNotStartNextTaskOrderIdList.contains(task.getOrderId()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(canStartNextTaskList)) {
            return;
        }

        // 对于可以开启下一节点的任务进行开启下一节点
        // 获取下一个节点的任务
        List<FlowRuTask> nextTaskList = getNextTaskList(canStartNextTaskList);
        List<String> nextTaskIdList = nextTaskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
        List<FlowRuTask> notExistsNextTaskList = canStartNextTaskList.stream()
                .filter(task -> !nextTaskIdList.contains(task.getOrderId())).collect(Collectors.toList());

        /* 没有下一节点，节点审批完成；如果有下一节点，开启了下一节点 */
        executeFinshFlowService(orderService, notExistsNextTaskList);

        /*20250703新增删除非制定人员*/
        deleteUnAppointApprovers(nextTaskList,handlerList) ;
        FlowHandler handler = handlerList.get(0) ;
        nextTaskList = nextTaskList.stream().filter(t -> handler.getAppointNextApprovers().contains(t.getUserId())).collect(Collectors.toList()) ;
        statNextTask(nextTaskList);
    }
    
    private void deleteUnAppointApprovers(List<FlowRuTask> taskList,List<FlowHandler> handlerList) {
    	FlowHandler handler = handlerList.get(0) ;
    	if(CollectionUtils.isEmpty(handler.getAppointNextApprovers())) {
    		return ;
    	}
    	
    	List<FlowRuTask> deleteTaskList = taskList.stream().filter(t -> !handler.getAppointNextApprovers().contains(t.getUserId())).collect(Collectors.toList()) ;

    	flowRuTaskDao.removeByIds(deleteTaskList.stream().map(FlowRuTask::getId).collect(Collectors.toList()));
    }

    private List<FlowRuTask> getRejectToTasks(List<FlowRuTask> taskList, String rejectNodeId,
                                              FlowAuditResult flowAuditResult) {
        List<String> orderIdList = taskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
        QueryWrapper<FlowRuTask> qw = new QueryWrapper<>();
        qw.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.agree.getCode()).eq(FlowRuTask::getNodeId,
                rejectNodeId);
        qw.lambda().in(FlowRuTask::getFlowId, orderIdList);

        List<FlowRuTask> rejectToTaskList = flowRuTaskDao.list(qw);

        rejectToTaskList.forEach(task -> {
            if (!orderIdList.contains(task.getOrderId())) {
                flowAuditResult.failOrderId(task.getOrderId())
                        .failMsg(String.format("单据[%s]在选择退回的流程节点还未审批，无法退回", task.getOrderId()));
            }
        });

        return rejectToTaskList;
    }

    private void handleRejectRuTask(List<FlowRuTask> rejectToTaskList) {
        // @1:将需要退回的单据退回到的节点之后的所有任务重置成未启动
        UpdateWrapper<FlowRuTask> uw1 = new UpdateWrapper<>();
        uw1.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.unstart.getCode()).set(FlowRuTask::getComments, "");
        uw1.lambda().and(wrapper -> rejectToTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).gt(FlowRuTask::getOrderNum,
                task.getOrderNum()))));
        flowRuTaskDao.update(uw1);

        // @2:将需要退回的单据退回到的节点的任务更新成未处理
        UpdateWrapper<FlowRuTask> uw2 = new UpdateWrapper<>();
        uw2.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode()).set(FlowRuTask::getComments, "");
        uw2.lambda().and(wrapper -> rejectToTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getOrderNum,
                task.getOrderNum()))));
        flowRuTaskDao.update(uw2);
    }

    /**
     * 批量退回
     *
     * @param taskList
     */
    private void rejectBatch(List<FlowRuTask> taskList, List<FlowHandler> handlerList,
                             FlowAuditResult flowAuditResult) {
        // 批量退回选择一个退回节点，退回节点一致
        String rejectNodeId = handlerList.get(0).getRejectNodeId();
        // 获取可以退回的任务
        List<FlowRuTask> rejectToTaskList = getRejectToTasks(taskList, rejectNodeId, flowAuditResult);

        // @1:处理ruTask状态
        handleRejectRuTask(rejectToTaskList);

        // @2：往任务执行日志中插入一条数据，标记开始时间
        FlowUtils.startTaskInHistory(flowHiTaskLogDao,rejectToTaskList) ;

        // @3:如果退回至初始节点，需要处理单据状态和hiflow的单据状态
        rejectToTaskList = rejectToTaskList.stream().filter(task -> task.getOrderNum() == 1)
                .collect(Collectors.toList());
        executeRejectToStartNode(rejectToTaskList);
    }

    /**
     * 批量退回
     *
     * @param taskList
     */
    private void rejectBatch(List<FlowRuTask> taskList) {
        List<String> businessKeyList = taskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
        List<String> flowIdList = taskList.stream().map(FlowRuTask::getFlowId).collect(Collectors.toList());

        // @1:将所有流程任务重置成未启动
        flowRuTaskDao.update(new UpdateWrapper<FlowRuTask>().lambda()
                .set(FlowRuTask::getStatus, FlowNodeStatusEnum.unstart.getCode()).set(FlowRuTask::getComments, "")
                .in(FlowRuTask::getFlowId, flowIdList));

        // @2:将第一个节点的任务更新成未处理
        // @3：往任务执行日志中插入一条数据，标记开始时间
        List<FlowRuTask> nextTaskList = flowRuTaskDao.list(new QueryWrapper<FlowRuTask>().lambda()
                .in(FlowRuTask::getFlowId, flowIdList).eq(FlowRuTask::getOrderNum, 1));
        flowRuTaskDao.update(new UpdateWrapper<FlowRuTask>().lambda()
                .set(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode()).set(FlowRuTask::getComments, "")
                .in(FlowRuTask::getId, nextTaskList.stream().map(FlowRuTask::getId).collect(Collectors.toList())));
        FlowUtils.startTaskInHistory(flowHiTaskLogDao,nextTaskList) ;

        // @4：将hiFlow的单据状态更新成编制中
        flowHiFlowDao.update(new UpdateWrapper<FlowHiFlow>().lambda()
                .set(FlowHiFlow::getOrderStatus, OrderStatusEnum.EDIT.getCode()).in(FlowHiFlow::getId, flowIdList));

        // @5:执行单据的退回服务
        // 批量审批只支持同一类单据,取第一个任务的单据服务
        FlowRuFlow ruFlow = flowRuFlowDao.getById(taskList.get(0).getFlowId());
        String orderService = ruFlow.getOrderService();
//        FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_REJECT_BATCH, businessKeyList);
        if(orderService.contains(".")) {
        	FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_REJECT_BATCH, businessKeyList);
        }else {
        	OrderFlowUtilsV2.rejectBatch(orderService, businessKeyList);
        }
    }

    private void executeRejectToStartNode(List<FlowRuTask> rejectToTaskList) {
        if (CollectionUtils.isEmpty(rejectToTaskList)) {
            return;
        }

        List<String> flowIdList = rejectToTaskList.stream().map(FlowRuTask::getFlowId).collect(Collectors.toList());
        List<String> businessKeyList = rejectToTaskList.stream().map(FlowRuTask::getOrderId)
                .collect(Collectors.toList());

        // @1：将hiFlow的单据状态更新成编制中
        flowHiFlowDao.update(new UpdateWrapper<FlowHiFlow>().lambda()
                .set(FlowHiFlow::getOrderStatus, OrderStatusEnum.EDIT.getCode()).in(FlowHiFlow::getId, flowIdList));

        // @2:执行单据的退回服务
        // 批量审批只支持同一类单据,取第一个任务的单据服务
        FlowRuFlow ruFlow = flowRuFlowDao.getById(rejectToTaskList.get(0).getFlowId());
        String orderService = ruFlow.getOrderService();
//        FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_REJECT_BATCH, businessKeyList);
        if(orderService.contains(".")) {
        	FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_REJECT_BATCH, businessKeyList);
        }else {
        	OrderFlowUtilsV2.rejectBatch(orderService, businessKeyList);
        }
    }

    /**
     * 如果是第一个流程节点进行审核，执行的是提交
     *
     * @param orderService
     * @param currentTaskList
     * @param handlerList
     */
    private void excuteSubmitFlow(String orderService, List<FlowRuTask> currentTaskList,
                                  List<FlowHandler> handlerList) {
        // 对于第一个任务节点处理，即单据提交操作执行逻辑
        List<FlowRuTask> orderNum1TaskList = currentTaskList.stream().filter(task -> 1 == task.getOrderNum())
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderNum1TaskList)) {
            return;
        }

        // 提交操作@1：将历史流程表中的单据状态改成审批中
        List<String> flowIdList = orderNum1TaskList.stream().map(FlowRuTask::getFlowId).collect(Collectors.toList());
        flowHiFlowDao.update(new UpdateWrapper<FlowHiFlow>().lambda()
                .set(FlowHiFlow::getOrderStatus, OrderStatusEnum.APPROVAL.getCode()).in(FlowHiFlow::getId, flowIdList));

        // 提交操作@2：执行单据的提交服务
        List<String> businessKeyList = handlerList.stream().map(FlowHandler::getBusinessKey)
                .collect(Collectors.toList());
        
        if(orderService.contains(".")) {
        	FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_SUBMIT_BATCH, businessKeyList);
        }else {
        	OrderFlowUtilsV2.submitBatch(orderService, businessKeyList);
        }
        
    }

    /**
     * 获取任务的当前节点是会签的单据
     *
     * @param currentTaskList
     * @return
     */
    private Map<String, List<String>> getHuiqOrderIdList(List<FlowRuTask> currentTaskList) {
        QueryWrapper<FlowRuNode> query = new QueryWrapper<>();
        currentTaskList.forEach(cTask -> query.lambda().or(wrapper -> wrapper.eq(FlowRuNode::getId, cTask.getNodeId()).eq(FlowRuNode::getFlowId,
                cTask.getFlowId())));
        List<FlowRuNode> nodeList = flowRuNodeDao.list(query);

        /*
         如果是会签，查找同级并且是待处理的任务，如果有任务不需要处理，如果没有任务，开启下一个节点任务。
         如果是或签，将同级的待处理任务，更新成nohandle，并开启下一个节点。
         */
        List<String> counterSignHuiqList = new ArrayList<>();
        List<String> counterSignHuoqList = new ArrayList<>();

        nodeList.forEach(node -> {
            if (FlowConstant.COUNTER_SIGN_HUIQ.equals(node.getCounterSign())) {
                counterSignHuiqList.add(node.getOrderId());
            } else {
                counterSignHuoqList.add(node.getOrderId());
            }
        });
        Map<String, List<String>> counterSignMap = new HashMap<>();
        counterSignMap.put("huiq", counterSignHuiqList);
        counterSignMap.put("huoq", counterSignHuoqList);

        return counterSignMap;
    }

    /**
     * 对于或签的任务，如果是有一个人审核了，其他的任务状态设置成nohandle
     *
     * @param counterSignHuoqList
     * @param currentTaskList
     */
    private void executeNoHandleTask(List<String> counterSignHuoqList, List<FlowRuTask> currentTaskList) {
        if (CollectionUtils.isEmpty(counterSignHuoqList)) {
            return;
        }

        List<FlowRuTask> huoqTaskList = currentTaskList.stream()
                .filter(task -> counterSignHuoqList.contains(task.getOrderId())).collect(Collectors.toList());

        UpdateWrapper<FlowRuTask> uw1 = new UpdateWrapper<>();
        uw1.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.nohandle.getCode()).set(FlowRuTask::getComments, "");
        uw1.lambda().and(wrapper -> huoqTaskList.forEach(cTask -> wrapper.or(wp -> wp.eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode())
                .eq(FlowRuTask::getOrderId, cTask.getOrderId())
                .eq(FlowRuTask::getOrderNum, cTask.getOrderNum()))));
        flowRuTaskDao.update(uw1);

        QueryWrapper<FlowHiTaskLog> uw2 = new QueryWrapper<>();
        uw2.lambda().and(wrapper -> huoqTaskList.forEach(cTask -> wrapper.or(wp -> wp.eq(FlowHiTaskLog::getStatus, FlowNodeStatusEnum.unhandle.getCode())
                .eq(FlowRuTask::getOrderId, cTask.getOrderId())
                .eq(FlowRuTask::getOrderNum, cTask.getOrderNum()))));
        flowHiTaskLogDao.remove(uw2);
    }

    private List<String> getCanNotStartNextTaskOrderIdList(List<String> counterSignHuiqList,
                                                           List<FlowRuTask> currentTaskList) {
        List<FlowRuTask> canNotStartNextTaskList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(counterSignHuiqList)) {
            List<FlowRuTask> huiqTaskList = currentTaskList.stream()
                    .filter(task -> counterSignHuiqList.contains(task.getOrderId())).collect(Collectors.toList());

            QueryWrapper<FlowRuTask> query1 = new QueryWrapper<>();
            query1.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode());
            query1.lambda().and(wrapper -> huiqTaskList.forEach(cTask -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, cTask.getOrderId()).eq(FlowRuTask::getOrderNum,
                    cTask.getOrderNum()))));
            canNotStartNextTaskList = flowRuTaskDao.list(query1);
            canNotStartNextTaskList = canNotStartNextTaskList == null ? new ArrayList<>() : canNotStartNextTaskList;
        }

        return canNotStartNextTaskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
    }

    private List<FlowRuTask> getNextTaskList(List<FlowRuTask> canStartNextTaskList) {
        QueryWrapper<FlowRuTask> qw = new QueryWrapper<>();
        qw.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unstart.getCode());
        qw.lambda().and(wrapper -> canStartNextTaskList.forEach(cTask -> wrapper.or(wp -> wp.eq(FlowRuTask::getFlowId, cTask.getFlowId()).eq(FlowRuTask::getOrderNum,
                cTask.getOrderNum() + 1))));
        return flowRuTaskDao.list(qw);
    }

    private void statNextTask(List<FlowRuTask> nextTaskList) {
        if (CollectionUtils.isEmpty(nextTaskList)) {
            return;
        }

        // @1:将下一节点的任务由未开启的状态更新成未处理
        flowRuTaskDao.update(new UpdateWrapper<FlowRuTask>().lambda()
                .set(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode())
                .in(FlowRuTask::getId, nextTaskList.stream().map(FlowRuTask::getId).collect(Collectors.toList())));

        // @2：往任务执行日志中插入一条数据，标记开始时间
        FlowUtils.startTaskInHistory(flowHiTaskLogDao,nextTaskList) ;
        
        //@3:增加监听器执行，当到达当前节点执行
//        ((FlowTaskService) AopContext.currentProxy()).executeListener(nextTaskList) ;
        try {
        	executeListener(nextTaskList) ;
        }catch(Exception e) {
        	e.printStackTrace(); 
        }
    }
    
    @Async
    public void executeListener(List<FlowRuTask> nextTaskList) {
    	if(CollectionUtils.isEmpty(nextTaskList)) {
    		return ;
    	}
    	for(FlowRuTask task : nextTaskList) {
        	QueryWrapper<FlowRuNode> qw = new QueryWrapper<>() ;
        	qw.lambda().eq(FlowRuNode::getId, task.getNodeId()).eq(FlowRuNode::getFlowId, task.getFlowId()).eq(FlowRuNode::getOrderId, task.getOrderId()) ;
        	FlowRuNode flowRuNode = flowRuNodeDao.getOne(qw) ;
        	String listenerService = flowRuNode.getListener() ;
        	//如果没有配置监听器，不执行
        	if(listenerService == null || "".equals(listenerService)) {
        		continue ;
        	}
        	
        	Listener listener;
            try {
            	listener = SpringContextUtil.getBean(listenerService,Listener.class);
            } catch (Exception e) {
                throw new ChuangkeException(String.format("流程审批节点未找到监听器[%s]", listenerService), e);
            }
            ListenerVariable lv = new ListenerVariable() ;
            lv.setTask(task);
            listener.notify(lv);
        }
    }

    private void executeFinshFlowService(String orderService, List<FlowRuTask> canFinshTaskList) {
        if (CollectionUtils.isEmpty(canFinshTaskList)) {
            return;
        }

        // @1:将ru表内的所有流程信息删除，只保留在hi表中
        List<String> canFinshFlowOrderIdList = canFinshTaskList.stream().map(FlowRuTask::getOrderId)
                .collect(Collectors.toList());
        //删除运行中流程信息;流程审批完成之后，删除运行中的流程信息
        flowInstanceService.deleteRuFlowInfoByOrderId(canFinshFlowOrderIdList);

        // @2:更新hiFlow的单据状态为已完成
        List<String> endFlowIdList = canFinshTaskList.stream().map(FlowRuTask::getFlowId).collect(Collectors.toList());
        flowHiFlowDao.update(new UpdateWrapper<FlowHiFlow>().lambda()
                .set(FlowHiFlow::getOrderStatus, OrderStatusEnum.COMPLETE.getCode())
                .in(FlowHiFlow::getId, endFlowIdList));

        // @3:执行单据的单据结束服务
        List<String> businessKeyList = canFinshTaskList.stream().map(FlowRuTask::getOrderId)
                .collect(Collectors.toList());
//        FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_COMPLETE_BATCH, businessKeyList);
        if(orderService.contains(".")) {
        	FlowUtils.handleOrderBatch(orderService, FlowConstant.HANDLE_ORDER_COMPLETE_BATCH, businessKeyList);
        }else {
        	OrderFlowUtilsV2.completeBatch(orderService, businessKeyList);
        }
    }

    /**
     * 获取到当前正在执行的任务
     *
     * @param handlerList
     * @param flowAuditResult
     * @return
     */
    private List<FlowRuTask> getCurrentHandleTaskByOrderIds(List<FlowHandler> handlerList,
                                                            FlowAuditResult flowAuditResult) {
        List<String> orderList = handlerList.stream().map(FlowHandler::getBusinessKey).collect(Collectors.toList());

        List<FlowRuTask> taskList = flowRuTaskDao
                .list(new QueryWrapper<FlowRuTask>().lambda().in(FlowRuTask::getOrderId, orderList)
                        .eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode()));

        if (CollectionUtils.isEmpty(taskList)) {
            throw new ChuangkeException("流程已审批完成，无法撤回");
        }

        List<String> existsOrderList = taskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
        orderList.forEach(orderId -> {
            if (!existsOrderList.contains(orderId)) {
                flowAuditResult.failOrderId(orderId).failMsg(String.format("单据[%s]流程已审批完成，无法撤回", orderId));
            }
        });

        taskList = taskList.stream().filter(task -> {
            if (task.getOrderNum() == 1) {
                flowAuditResult.failOrderId(task.getOrderId())
                        .failMsg(String.format("单据[%s]未提交，无需撤回", task.getOrderId()));
            }
            return task.getOrderNum() > 1;
        }).collect(Collectors.toList());

        return taskList;
    }

    /**
     * 根据当前执行中的任务获取可以撤回的任务
     *
     * @param taskList
     * @param flowAuditResult
     * @return
     */
    private List<FlowRuTask> getCanRevokeTaskList(String userId, List<FlowRuTask> taskList,
                                                  FlowAuditResult flowAuditResult) {
        // 获取当前待处理任务的上一个任务节点（审核人是当前用户）的任务
        QueryWrapper<FlowRuTask> query = new QueryWrapper<>();
        query.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.agree.getCode());
        query.lambda().and(wrapper -> taskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getUserId, userId)
                .eq(FlowRuTask::getOrderNum, task.getOrderNum() - 1))));
        List<FlowRuTask> canRevokeTaskList = flowRuTaskDao.list(query);
        List<String> canRevokeTaskIdList = taskList.stream().map(FlowRuTask::getOrderId).collect(Collectors.toList());
        taskList.forEach(task -> {
            if (!canRevokeTaskIdList.contains(task.getOrderId())) {
                flowAuditResult.failOrderId(task.getOrderId())
                        .failMsg(String.format("单据[%s]下一节点已审核，无法撤回", task.getOrderId()));
            }
        });
        return canRevokeTaskList;
    }

    /**
     * 处理任务节点状态
     *
     * @param canRevokeTaskList 需要撤回到的节点
     */
    private void handleRevokeRuTask(List<FlowRuTask> canRevokeTaskList) {
        if (CollectionUtils.isEmpty(canRevokeTaskList)) {
            return;
        }

        // @1:将上一节点的任务状态更新成未启动
        UpdateWrapper<FlowRuTask> uw1 = new UpdateWrapper<>();
        uw1.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.unstart.getCode()).set(FlowRuTask::getComments, "");
        uw1.lambda().and(wrapper -> canRevokeTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getOrderNum,
                task.getOrderNum() + 1))));
        flowRuTaskDao.update(uw1);

        // @2：将当前任务的节点处理状态由同意更新成未处理
        UpdateWrapper<FlowRuTask> uw2 = new UpdateWrapper<>();
        uw2.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode()).set(FlowRuTask::getComments, "");
        uw2.lambda().and(wrapper -> canRevokeTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getOrderNum,
                task.getOrderNum()))));

		/*
		  执行审核，并将任务放到历史任务中
		 */
        // 当前节点置成未启动，上一节点置成待处理

        flowRuTaskDao.update(uw2);
    }

    private void handleRevokeHiTaskLog(List<FlowRuTask> canRevokeTaskList, List<FlowHandler> handlerList) {
		/*
		  @1：处理之前待处理的人任务日志
		 * @2：插入退回至的节点待处理任务日志
		 * 
		 * @处理之前待处理的人任务日志的思路
		 * @思路1：将之前的待处理的任务日志删掉，插入撤回的日志
		 * @思路2：将之前的待处理的任务日志更新,更新之前，先将有多个人同时审的删除只留一条
		 * @当前选择思路2
		 */
        QueryWrapper<FlowHiTaskLog> qw = new QueryWrapper<>();
        qw.lambda().eq(FlowHiTaskLog::getStatus, FlowNodeStatusEnum.unhandle.getCode());
        qw.lambda().and(wrapper -> canRevokeTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getOrderNum,
                task.getOrderNum() + 1))));
        List<FlowHiTaskLog> taskLogList = flowHiTaskLogDao.list(qw);

        List<String> exitsLogList = new ArrayList<>();
        List<String> canDeleteLogList = new ArrayList<>();
        taskLogList.forEach(log -> {
            String key = log.getOrderId() + "-" + log.getOrderNum();
            if (!exitsLogList.contains(key)) {
                exitsLogList.add(key);
            } else {
                canDeleteLogList.add(log.getId());
            }
        });

        if (!CollectionUtils.isEmpty(canDeleteLogList)) {
            QueryWrapper<FlowHiTaskLog> deleteQw = new QueryWrapper<>();
            deleteQw.lambda().in(FlowHiTaskLog::getId, canDeleteLogList);
            flowHiTaskLogDao.remove(deleteQw);
        }

        String auditMessage = handlerList.get(0).getMessage();
        String userId = handlerList.get(0).getUserId();
        UpdateWrapper<FlowHiTaskLog> uw3 = new UpdateWrapper<>();
        uw3.lambda().set(FlowRuTask::getStatus, FlowNodeStatusEnum.revoke.getCode())
                .set(FlowRuTask::getComments, auditMessage).set(FlowHiTaskLog::getEndAt, new Date())
                .set(FlowHiTaskLog::getUserId, userId);
        uw3.lambda().eq(FlowHiTaskLog::getStatus, FlowNodeStatusEnum.unhandle.getCode());
        uw3.lambda().and(wrapper -> canRevokeTaskList.forEach(task -> wrapper.or(wp -> wp.eq(FlowRuTask::getOrderId, task.getOrderId()).eq(FlowRuTask::getOrderNum,
                task.getOrderNum() + 1))));

        flowHiTaskLogDao.update(uw3);

        FlowUtils.startTaskInHistory(flowHiTaskLogDao,canRevokeTaskList) ;
    }

}
